package com.rockcent.mall.lib.repository;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.common.SQLListDoing;
import com.rockcent.common.common.SQLObjectDoing;
import com.rockcent.common.common.SQLPageDoing;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.RDateFormatUtils;
import com.rockcent.common.utils.RDateUtils;
import com.rockcent.mall.lib.domain.enumclass.CouponType;
import com.rockcent.mall.lib.domain.enumclass.CustomerCouponWalletStatus;
import com.rockcent.mall.lib.dto.CustomerCouponWalletDto;
import com.rockcent.mall.lib.dto.GiftVerifyDto;
import com.rockcent.mall.lib.dto.GiftVerifyItemDto;
import com.rockcent.mall.lib.dto.MerchantCouponDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * Created by DK on 16/10/22.
 */
@Repository
public class CustomerCouponWalletRepositoryImpl implements CustomerCouponWalletRepositoryCustom {

    private static final Logger log = LoggerFactory.getLogger(CustomerCouponWalletRepositoryImpl.class);

    @Autowired
    private NamedParameterJdbcTemplate jdbcTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public PageResult<MerchantCouponDto> findCustomerCouponPage(Long customerId, String couponStatus, PageResult pageResult) {
        SQLPageDoing<MerchantCouponDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("SELECT %s FROM customer_coupon_wallet ccw LEFT JOIN coupon c ON ccw.coupon_id = c.id left join merchant m on ccw.merchant_id = m.id WHERE 1=1");
            sql.append(" AND ccw.customer_id =:customerId");
            sql.append(" AND ccw.is_delete = :isDelete");
            params.put("customerId", customerId);
            if (CustomerCouponWalletStatus.EXPIRED == CustomerCouponWalletStatus.valueOf(couponStatus)) {
                sql.append(" AND c.date_disabled < :nowDate ");
                params.put("nowDate", RDateFormatUtils.format(new java.util.Date()));
            } else {
                sql.append(" AND ccw.status = :couponStatus");
                params.put("couponStatus", couponStatus);
            }

            params.put("isDelete", Whether.NO.toString());
            sql.append(" ORDER BY ccw.date_created desc");
            fields.append("c.*, ccw.id customerCouponId, m.name merchantName");
        };
        return doing.go(pageResult, MerchantCouponDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public MerchantCouponDto findCustomerCouponInfo(Long id, Long customerId) {
        SQLObjectDoing<MerchantCouponDto> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select %s from customer_coupon_wallet ccw LEFT JOIN coupon c ON ccw.coupon_id = c.id WHERE 1=1");
            sql.append(" AND ccw.customer_id =:customerId");
            sql.append(" AND ccw.id =:id");
            params.put("customerId", customerId);
            params.put("id", id);
            fields.append("c.*");
        };
        return doing.go(MerchantCouponDto.class, jdbcTemplate, log, objectMapper);
    }

    public Long countByCustomerIdAndDateDisabledBeforeNow(Long customerId) {
        SQLObjectDoing<Long> doing = (sql, fields, params, typeReferenceMap) -> {
            sql.append("select count(1) from customer_coupon_wallet ccw LEFT JOIN coupon c ON ccw.coupon_id = c.id WHERE 1=1 ");
            sql.append(" AND ccw.customer_id = :customerId AND c.date_disabled < now() ");
            params.put("customerId", customerId);
        };
        return doing.go(Long.class, jdbcTemplate, log, objectMapper);
    }

    @Override
    public PageResult<CustomerCouponWalletDto> findMerchantCouponVerificationPage(Long merchantId, Long merchantStoreId, String couponType, String keyword, String beginDate, String endDate, PageResult pageResult) {
        SQLPageDoing<CustomerCouponWalletDto> doing = (sql, fields, params, typeReferenceMaP) -> {
            sql.append("select %s from customer_coupon_wallet ccw left join coupon c on ccw.coupon_id = c.id where 1=1");

            if (CouponType.ALL != CouponType.valueOf(couponType)) {
                sql.append(" c.type = :couponType");
                params.put("couponType", couponType);
            }

            if (merchantId != null) {
                sql.append(" and ccw.merchant_id = :merchantId");
                params.put("merchantId", merchantId);
            }
            if (merchantStoreId != null) {
                sql.append(" and c.merchant_store_id = :merchantStoreId");
                params.put("merchantStoreId", merchantStoreId);
            }
            if (StringUtils.isNotBlank(keyword)) {
                sql.append(" AND (c.id =:key  OR c.name  LIKE :keyword)");
                params.put("key", keyword);
                params.put("keyword", "%" + keyword + "%");
            }

            sql.append(" AND ccw.date_created < :endDate AND ccw.date_created > :beginDate");
            params.put("beginDate", RDateUtils.beforeDateStr(beginDate, 0));
            params.put("endDate", RDateUtils.afterDateStr(endDate, 1));
            sql.append(" and ccw.status = 'USED'");
            sql.append(" order by ccw.date_created desc");

            fields.append("ccw.*, ccw.customer_name customerName, c.name couponName, c.logo_url logoUrl, c.introduction, c.face_value faceValue ,c.discount, c.limit_amount limitAmount, c.type couponType");
        };
        return doing.go(pageResult, CustomerCouponWalletDto.class, objectMapper, jdbcTemplate, log);
    }

    @Override
    public List<MerchantCouponDto> findOrderForMyCoupon(Long customerId, List<Long> merchantIdList) {
        SQLListDoing<MerchantCouponDto> doing = (sql, fields, params, map) -> {
            sql.append("select %s from customer_coupon_wallet ccw left join coupon c on ccw.coupon_id = c.id where 1=1 and ccw.status = 'TO_USE'");
            sql.append(" and ccw.customer_id = :customerId");
            params.put("customerId", customerId);
            sql.append(" and ccw.merchant_id in (:merchantIdList)");
            params.put("merchantIdList", merchantIdList);
            fields.append("c.*, ccw.id customerCouponId");
        };
        return doing.go(MerchantCouponDto.class, jdbcTemplate, log, objectMapper);
    }

    @Override
    public List<GiftVerifyItemDto> findCustomerCouponByVerifyPersonId(Long customerId, Long verifyId) {

        SQLListDoing<GiftVerifyItemDto> doing = (sql, fields, params, map) -> {
            sql.append("SELECT %s FROM customer_coupon_wallet ccw LEFT JOIN coupon c ON ccw.coupon_id = c.id left join merchant m on ccw.merchant_id = m.id WHERE 1=1");
            sql.append(" AND ccw.customer_id =:customerId");
            sql.append(" AND ccw.is_delete = :isDelete");
            params.put("customerId", customerId);
            sql.append(" AND ccw.status = :couponStatus");
            params.put("couponStatus", "TO_USE");

            params.put("isDelete", Whether.NO.toString());
            sql.append(" ORDER BY ccw.date_created desc");
            fields.append("c.*, ccw.id customerCouponId, m.name merchantName");

        };
        return doing.go(GiftVerifyItemDto.class, jdbcTemplate, log, objectMapper);
    }

}
